﻿using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace TableTool;
public class GlobalKeyboardHook
{
    // 定义键盘钩子常量
    public const int WH_KEYBOARD_LL = 13;
    public const int WM_KEYDOWN = 0x0100;
    public const int WM_KEYUP = 0x0101;

    // 保存钩子的委托和句柄
    public static IntPtr _hookID = IntPtr.Zero;
    public static LowLevelKeyboardProc _proc = HookCallback;

    //public static void Main()
    //{
    //    // 设置钩子
    //    _hookID = SetHook(_proc);
    //    Application.Run();
    //    UnhookWindowsHookEx(_hookID);
    //}

    // 设置全局钩子
    public static IntPtr SetHook(LowLevelKeyboardProc proc)
    {
        using (Process curProcess = Process.GetCurrentProcess())
        using (ProcessModule curModule = curProcess.MainModule)
        {
            return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
        }
    }

    // 钩子回调函数
    public delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);

    public static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
    {
        if (nCode >= 0 && (wParam == (IntPtr)WM_KEYDOWN || wParam == (IntPtr)WM_KEYUP))
        {
            int vkCode = Marshal.ReadInt32(lParam); // 获取按键的虚拟码
            Keys key = (Keys)vkCode;

            // 按键按下事件
            if (wParam == (IntPtr)WM_KEYDOWN)
            {
                Console.WriteLine($"Key Down: {key}");
            }

            // 按键松开事件
            if (wParam == (IntPtr)WM_KEYUP)
            {
                Console.WriteLine($"Key Up: {key}");
            }
        }

        // 调用下一个钩子
        return CallNextHookEx(_hookID, nCode, wParam, lParam);
    }

    /// <summary>
    /// 引用User32.dll的相关函数
    /// </summary>
    /// <param name="idHook"></param>
    /// <param name="lpfn"></param>
    /// <param name="hMod"></param>
    /// <param name="dwThreadId"></param>
    /// <returns></returns>
    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern IntPtr GetModuleHandle(string lpModuleName);
}
